// 题目描述：
// 给你一个非负整数数组 nums ，你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

// 判断你是否能够到达最后一个下标，如果可以，返回 true ；否则，返回 false 。

 

// 示例 1：

// 输入：nums = [2,3,1,1,4]
// 输出：true
// 解释：可以先跳 1 步，从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
// 示例 2：

// 输入：nums = [3,2,1,0,4]
// 输出：false
// 解释：无论怎样，总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 ， 所以永远不可能到达最后一个下标。

// 自己的答案(答案错误，没解出来)：
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
    const calculateNums = (i) => {
        for (let j = i; j < i + nums[i]; j++) {
            const jumpLengthSecond = nums.length - 1 - j;
            console.log('j', nums[j], jumpLengthSecond)
            if(nums[j] >= jumpLengthSecond) {
            console.log('jtrue', nums[j], jumpLengthSecond)
                return true
            } else if(j === nums.length - 1 || nums[j] === 0) {
                return false
            } else {
                calculateNums(j + 1)
            }
        }
    }
    // if(nums.length === 1) {
    //     return true
    // } else if(nums[nums.length - 2] === 0 || nums[0] === 0) {
    //     return false
    // }
    
    for (let i = 0; i < nums.length; i++) {
        const jumpLength = nums.length - 1 - i;
        console.log('i', nums[i], jumpLength)
        if(i === nums.length - 2 && nums[i] === 0 || nums.length > 1 && nums[0] === 0) {
            return false
        } else if(nums.length === 1 || nums[i] >= jumpLength) {
            return true
        } else {
            // for (let j = i; j < i + nums[i]; j++) {
            //     const jumpLengthSecond = nums.length - 1 - j;
            //     console.log('j', nums[j], jumpLengthSecond)
            //     if(nums[j] === jumpLengthSecond) {
            //         return true
            //     }
            // }
            calculateNums(i)
        }
    }
    return false
};
console.log(canJump([3,2,1,0,4]));


// Gpt答案：
function canJump(nums) {  
    let maxReach = 0; // 当前能够到达的最远位置  
    for (let i = 0; i < nums.length; i++) {  
        // 如果当前位置超过了能够到达的最远位置，则无法继续向前移动  
        if (i > maxReach) {  
            return false;  
        }  
        // 更新能够到达的最远位置  
        maxReach = Math.max(maxReach, i + nums[i]);  
        // 如果最远位置已经覆盖到数组的最后一个位置，则返回 true  
        if (maxReach >= nums.length - 1) {  
            return true;  
        }  
    }  
    return false; // 理论上这个返回语句不会被执行到，因为上面的条件已经覆盖了所有情况  
}  
  
// 示例测试  
console.log(canJump([2, 3, 1, 1, 4])); // 输出: true  
console.log(canJump([3, 2, 1, 0, 4])); // 输出: false

// 官方题解：
var canJump = function(nums) {
    let mx = 0; // 
    for (let i = 0; i < nums.length - 1; i++) { // 因为最后一个元素无需跳跃，所以这里的循环可以 -1
        if (i > mx) { // 无法到达 i
            return false;
        }
        mx = Math.max(mx, i + nums[i]); // 从 i 最右可以跳到 i + nums[i]（在 i 位置从最左开始算能跳的最远距离）
    }
    return true;
};

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
    // 必须到达end下标的数字
    let end = nums.length - 1;

    for (let i = nums.length - 2; i >= 0; i--) {
        if (end - i <= nums[i]) { // 等价于自己做题中的 jumpLength
            end = i;
        }
    }

    return end == 0;
};